package moa.learners.reservoir;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;

import com.espertech.esper.collection.Pair;

/**
 * This class implements the Reservoir itself.
 * 
 * In order to allow efficient operations and be conform
 * to the parent class, the sequence IDs are stored in
 * an ArrayList to be indexed easily while the values are 
 * stored in an HashMap.
 *
 * @param <E> type of the itemsets to be stored
 */
public class IndexedSlides<E> extends AbstractSlides<E> {

	ArrayList<String> indexReserv;
	HashMap<String,LinkedList<E>> tableReserv;

	/**
	 * @param cardSd	number of sequences to store
	 * @param winSize	sliding window size for each sequence
	 */
	public IndexedSlides(int cardSd, int winSize) {
		super(cardSd, winSize);

		indexReserv = new ArrayList<String>();
		tableReserv = new HashMap<String, LinkedList<E>>();
	}

	@Override
	public boolean hasSequenceNumber( String seqNumber) {
		return tableReserv.containsKey(seqNumber);
	}

	@Override
	public boolean addAndSlide(String seqNumber, E itemSet) {
		LinkedList<E> slide = tableReserv.get(seqNumber);
		slide.addLast(itemSet);
		if( slide.size() > winSize)
		{
			slide.removeFirst();
			return true;
		}
		return false;
	}

	@Override
	public int getNbSequences() {
		return indexReserv.size();
	}



	public Pair<String, Integer> replace(int loto, String seqNumber, E itemSet) {
		String remSeqNumber = indexReserv.get(loto);

		Pair<String, Integer> result ;
		result = new com.espertech.esper.collection.Pair<String, Integer>(remSeqNumber, tableReserv.get(remSeqNumber).size());
		tableReserv.remove(remSeqNumber);

		LinkedList<E> sequence = new LinkedList<E>();
		sequence.add(itemSet);

		indexReserv.set(loto, seqNumber);
		tableReserv.put(seqNumber, sequence);

		return result;
	}

	@Override
	public void addSequence(String seqNumber, E itemSet) {
		if(indexReserv.size() >= cardSd)
			throw new IllegalStateException("addSequence called even though the Reservoir is full");

		LinkedList<E> sequence = new LinkedList<E>();
		sequence.add(itemSet);

		indexReserv.add(seqNumber);
		tableReserv.put(seqNumber, sequence);
	}

	@Override
	public Iterator<String> clientIterator() {
		return indexReserv.iterator();
	}

	@Override
	public Iterator<E> itemIterator( String client) {
		return tableReserv.get(client).iterator();
	}
}
